#pragma once
#include "Thread.hpp"
#include <queue>
#include <iostream>
#include <pthread.h>
#include <functional>
#include <vector>
#include "Task.hpp"
#include"Log.hpp"
#define threadNum 4
#define taskNum 3

using namespace threadMould;
class ThreadPool
{
private:
    void HandleTask(const std::string &name)
    {
        while (true)
        {
            // 从queue中拿任务
            Lock();
          
            // 任务队列为空就去休眠
            while (IsEmpty() && _isrunning)
            {
                _sleep++;
            LOG(DEBUG,"%s HAS Sleep",name.c_str());

                Sleep();
            LOG(DEBUG,"%s HAS Wake",name.c_str());

                _sleep--;
            }
              // 如果任务队列为空,且为退出状态就退出
            if (IsEmpty() && !_isrunning)
            {
                UnLock();
                break;
            }

            Task t = _queue.front();
            _queue.pop();
            UnLock();
            // 执行任务，在锁外实现串行
            t.Exute();
            LOG(DEBUG,"%s is tasking",name.c_str());

        }
    }
    void Sleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnLock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void Wake()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeAll()
    {
        pthread_cond_broadcast(&_cond);
    }
    bool IsEmpty()
    {
        return _queue.size() == 0;
    }

public:
    ThreadPool()
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    void Init()
    {
        // 创建一批线程（未启动），此时任务队列为空
        func_t func = std::bind(&ThreadPool::HandleTask, this, std::placeholders::_1);
        for (int i = 0; i < threadNum; i++)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back(name, func);
            LOG(DEBUG,"%s HAS INITED",name.c_str());
        }
    }
    void Start()
    {
        _isrunning = true;
        for (auto &e : _threads)
        {
            e.Start();
            LOG(DEBUG,"%s HAS START",e.Name().c_str());
        }
    }
    void Stop()
    {
        //必须加锁唤醒，保证之前的线程都已经进入等待
        //而不是，一部分线程在执行任务时（还没有去等待），而主线程在此时唤醒的话就会导致某些线程错过
        Lock();
        _isrunning = false;
         WakeAll();
       
        for (auto &e : _threads)
        {
            e.Join();
            LOG(DEBUG,"%s HAS end",e.Name().c_str());

        }
        UnLock();
       
        
    }
    // 往任务队列添加任务
    void Equeue(Task &in)
    {
        // 线程池运行才推任务
        if (_isrunning)
        {
            Lock();
            if (_queue.size() > taskNum)
            {
                _queue.pop();
            }
            _queue.push(in);
            // 有任务了就唤醒线程
            if (_sleep > 0)
                Wake();
            UnLock();
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    std::vector<Thread> _threads;
    std::queue<Task> _queue;

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    bool _isrunning = false;

    int _sleep = 0; // 休眠线程数目
    //
};